﻿using System;
using System.Windows;
using System.Collections.Generic;
using System.Windows.Media;
using WickedFlame.Core.Shapes;

namespace WickedFlame.Core.State
{
    [Serializable]
    internal class PolygonMemento : ShapeMemento
    {
        Point startPoint;
        List<IPolygonSegment> segments = new List<IPolygonSegment>();
        bool _isSegmentsJoined;

        public override void SaveProperties(VectorShape shape)
        {
            base.SaveProperties(shape);

            var p = shape as PolygonShape;
            if (p != null)
            {
                startPoint = p.StartPoint;

                foreach (PathSegment segment in p.DefiningGeometry.Figures[0].Segments)
                {
                    if (segment is LineSegment)
                    {
                        segments.Add(new PolygonLineSegnent
                        {
                            Point = ((LineSegment)segment).Point,
                            IsStroked = ((LineSegment)segment).IsStroked
                        });
                    }
                    else if (segment is QuadraticBezierSegment)
                    {
                        segments.Add(new PolygonCurveSegment
                        {
                            Point1 = ((QuadraticBezierSegment)segment).Point1,
                            Point2 = ((QuadraticBezierSegment)segment).Point2,
                            IsStroked = ((QuadraticBezierSegment)segment).IsStroked
                        });
                    }
                    else if (segment is BezierSegment)
                    {
                        segments.Add(new PolygonSCurveSegment
                        {
                            Point1 = ((BezierSegment)segment).Point1,
                            Point2 = ((BezierSegment)segment).Point2,
                            Point3 = ((BezierSegment)segment).Point3,
                            IsStroked = ((BezierSegment)segment).IsStroked
                        });
                    }
                    else
                        throw new NotImplementedException("Segmenttype is not jet implemented");
                }

                _isSegmentsJoined = p.JoinEndSegments;
            }
        }

        public override void ResetProperties(VectorShape shape)
        {
            base.ResetProperties(shape);

            var p = shape as PolygonShape;
            if (p != null)
            {
                p.StartPoint = startPoint;

                p.DefiningGeometry.Figures[0].Segments.Clear();

                foreach (IPolygonSegment segment in segments)
                {
                    if (segment is PolygonLineSegnent)
                    {
                        //p.AddSegment(new LineSegment(
                        //    ((PolygonLineSegnent)segment).Point,
                        //    ((PolygonLineSegnent)segment).IsStroked), new Point());
                        p.DefiningGeometry.Figures[0].Segments.Add(new LineSegment(
                            ((PolygonLineSegnent)segment).Point,
                            ((PolygonLineSegnent)segment).IsStroked));
                    }
                    else if (segment is PolygonCurveSegment)
                    {
                        p.DefiningGeometry.Figures[0].Segments.Add(new QuadraticBezierSegment(
                            ((PolygonCurveSegment)segment).Point1,
                            ((PolygonCurveSegment)segment).Point2,
                            ((PolygonCurveSegment)segment).IsStroked));
                    }
                    else if (segment is PolygonSCurveSegment)
                    {
                        p.DefiningGeometry.Figures[0].Segments.Add(new BezierSegment(
                            ((PolygonSCurveSegment)segment).Point1,
                            ((PolygonSCurveSegment)segment).Point2,
                            ((PolygonSCurveSegment)segment).Point3,
                            ((PolygonSCurveSegment)segment).IsStroked));
                    }
                    else
                        throw new NotImplementedException("Segmenttype is not jet implemented");
                }

                p.JoinEndSegments = _isSegmentsJoined;
            }
        }

        public override VectorShape GenerateShape()
        {
            var shape = new PolygonShape();
            shape.ResetState(this);

            return shape;
        }

        private interface IPolygonSegment
        {
        }

        [Serializable]
        private struct PolygonLineSegnent : IPolygonSegment
        {
            public Point Point
            {
                get;
                set;
            }

            public bool IsStroked
            {
                get;
                set;
            }
        }

        [Serializable]
        private struct PolygonCurveSegment : IPolygonSegment
        {
            public Point Point1
            {
                get;
                set;
            }

            public Point Point2
            {
                get;
                set;
            }

            public bool IsStroked
            {
                get;
                set;
            }
        }

        [Serializable]
        private struct PolygonSCurveSegment : IPolygonSegment
        {
            public Point Point1
            {
                get;
                set;
            }

            public Point Point2
            {
                get;
                set;
            }

            public Point Point3
            {
                get;
                set;
            }

            public bool IsStroked
            {
                get;
                set;
            }
        }
    }
}
